#include "xyphonecontrol.h"
#include <QDate>
#include <QStandardPaths>
#include <QDir>
#include <QRandomGenerator>
#include <string>
#include <vector>
#include <QVariantMap>
#include <pjsua2/account.hpp>
#include <functional>
#include <utility>
#include <pjsua2/call.hpp>

XyPhoneControl::XyPhoneControl(QObject *parent) : QObject(parent)
{
    this->init();
    this->pjsipInit();
}

void XyPhoneControl::init()
{

}

void XyPhoneControl::pjsipInit()
{
    m_pEndpoint = new XyEndpoint(this);
    pj::EpConfig epconf;
    epconf.uaConfig.userAgent = std::string("zhuxy.f3322.net/version 1.0.0");
    epconf.medConfig.clockRate = 44100;
    epconf.medConfig.ecTailLen = PJSUA_DEFAULT_EC_TAIL_LEN;
    epconf.medConfig.channelCount = 2;
    epconf.logConfig.level = 5;
    epconf.logConfig.fileFlags = PJ_O_APPEND;
    QString strDate = QDate::currentDate().toString("yyyy-MM-dd");
    QString strLogDir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + QString("/xyphone/logs/");
    QDir xyDir(strLogDir);
    if(!xyDir.exists())
    {
        xyDir.mkdir(strLogDir);
    }
    QString xyLogFile = strLogDir + strDate + QString("_xyphone") + QString(".log");
    epconf.logConfig.filename = xyLogFile.toLocal8Bit().toStdString();
    try
    {
         m_pEndpoint->libCreate();
        m_pEndpoint->libInit(epconf);
    }
    catch (pj::Error& err)
    {
         pj::Endpoint::instance().utilLogWrite(1,std::string("xyctl"),err.info());
        return;
    }
    while(true)
    {
        int port = QRandomGenerator::global()->bounded(1024,65535);
        try
        {
            pj::TransportConfig xyTransConf;
            xyTransConf.port = port;
            m_pEndpoint->transportCreate(PJSIP_TRANSPORT_UDP,xyTransConf);
            m_pEndpoint->libStart();
            break;
        }
        catch (pj::Error& err)
        {
            pj::Endpoint::instance().utilLogWrite(1,std::string("xyctl"),err.info());
        }
    }
    pj::CodecInfoVector2 vecCodec = m_pEndpoint->codecEnum2();
    bool xyFind = false;
    std::string xyCodec("PCMA/8000/1");
    for(unsigned int i = 0;i < vecCodec.size(); ++i)
    {
        pj::Endpoint::instance().codecSetPriority(vecCodec[i].codecId,0);
        if(!vecCodec[i].codecId.compare(xyCodec))
        {
            pj::Endpoint::instance().codecSetPriority(xyCodec,255);
            xyFind = true;
        }
    }
    if(!xyFind)
    {
        pj::Endpoint::instance().utilLogWrite(1,std::string("xyctl"),"not found PCMA/8000/1");
    }
    pj::AudioDevInfoVector2 vecDev = pj::Endpoint::instance().audDevManager().enumDev2();
    for(unsigned int i = 0;i < vecDev.size();++i)
    {
        std::string xyLog = vecDev[i].driver + ":" + vecDev[i].name +":" +
                std::to_string(vecDev[i].inputCount) + std::to_string(vecDev[i].outputCount);
        pj::Endpoint::instance().utilLogWrite(1,std::string("xyctl"),xyLog);
    }
}

void XyPhoneControl::sipRegister(QVariantMap &mapParam)
{
    QString xySipAccountId = mapParam.value("sipAccountId").toString();
    QString xySipAccountName = mapParam.value("sipAccountName").toString();
    QString xySipPassword = mapParam.value("sipPassword").toString();
    QString xySipAddress = mapParam.value("sipAddress").toString();
    QString xySipPort = mapParam.value("sipPort").toString();
    QString xySipProxyAddress = mapParam.value("sipProxyAddress").toString();
    QString xySipProxyPort = mapParam.value("sipProxyPort").toString();
    QString xySipDomain = mapParam.value("sipDomain").toString();

    QString xySipRegisterUrl = QString("sip:") + xySipAddress + QString(":") + xySipPort;
    QString xySipProxyUrl = QString("sip:") + xySipProxyAddress + QString(":") + xySipProxyPort;

    QString xySipIdUrl = xySipAccountName + QString("<sip:") + xySipAccountId +
            QString("@") + xySipDomain + QString(">");

    pj::AuthCredInfo xyAuth;
    xyAuth.realm = std::string("*");
    xyAuth.scheme = std::string("Digest");
    xyAuth.username = xySipAccountId.toStdString();
    xyAuth.data = xySipPassword.toStdString();
    xyAuth.dataType = 0;

    pj::AccountConfig xyAcc;
    xyAcc.idUri = xySipIdUrl.toStdString();
    xyAcc.sipConfig.proxies.push_back(xySipProxyUrl.toStdString());
    xyAcc.regConfig.registrarUri = xySipRegisterUrl.toStdString();
    xyAcc.natConfig.iceEnabled = false;
    xyAcc.natConfig.contactRewriteUse = 2;
    xyAcc.natConfig.viaRewriteUse = 1;
    xyAcc.sipConfig.authCreds.push_back(xyAuth);

    try
    {
        if(m_Account.isValid())
        {
            m_Account.shutdown();
        }
        m_Account.create(xyAcc);
    }
    catch (pj::Error& err)
    {

    }
}

void XyPhoneControl::sipunRegister(QVariantMap &mapParam)
{
    if(m_Account.isValid())
    {
        m_Account.shutdown();
    }
}

void XyPhoneControl::sipCall(QVariantMap &mapParam)
{
    pj::CallOpParam xyParam;
    QString xyDestNumber = mapParam.value("destNumber").toString();
    QString xySipAddress = mapParam.value("sipAddress").toString();
    QString xySipId = QString("sip:") + xyDestNumber + QString("@") + xySipAddress;
    soundReset();
    /*
    try
    {
        if(!m_pCall)
        {
            m_pCall = new XyCall(m_Account,nullptr);
            m_pCall->makeCall(xySipId.toStdString(),xyParam);
        }
    }
    catch (pj::Error& err)
    {

    }
    */
}

void XyPhoneControl::sipHangup(QVariantMap &mapParam)
{

}

void XyPhoneControl::soundReset()
{
    try
    {
        pj::Endpoint::instance().audDevManager().refreshDevs();
        pj::Endpoint::instance().audDevManager().setEcOptions(0,0);
    }
    catch (pj::Error& err)
    {

    }
}
